
/**
  * 13.6	Manifest 上下文界定
  * Manifest 是 scala2.8 引入的一个特质，用于编译器在运行时也能获取泛型类型的信息。
  * 在 JVM 上，泛型参数类型 T 在运行时是被“擦拭”掉的，编译器把 T 当作 Object 来对待，
  * 所以 T 的具体信息是无法得到的；
  * 为了使得在运行时得到 T 的信息，
  * scala 需要额外通过 Manifest 来存储 T 的信息，
  * 并作为参数用在方法的运行时上下文。
  * def test[T] (x:T, m:Manifest[T]) { ...  }
  * 有了 Manifest[T]这个记录 T 类型信息的参数 m，
  * 在运行时就可以根据 m来更准确的判断 T 了。但如果每个方法都这么写，
  * 让方法的调用者要额外传入 m 参数， 非常不友好，且对方法的设计是一道伤疤。
  * 好在 scala 中有隐式转换、隐式参数的功能，在这个地方可以用隐式参数来减轻调用者的麻烦。
  */

def foo[T](x: List[T])(implicit m: Manifest[T]) = {
  println(m)
  if (m <:< manifest[String])
    println("Hey, this list is full of strings")
  else
    println("Non-stringy list")
}

foo(List("one", "two")) // Hey, this list is full of strings
foo(List(1, 2)) // Non-stringy list
foo(List("one", 2)) // Non-stringy list


import scala.reflect._

def makePair[T : ClassTag](first: T, second: T) = {
    val r = new Array[T](2); r(0) = first; r(1) = second; r
}

val a = makePair(4, 2) // An Array[Int]
a.getClass // In the JVM, [I is an int[] array

val b = makePair("Fred", "Brooks") // An Array[String]
b.getClass // In the JVM, [Ljava.lang.String; is a String[] array